#ifndef FIXED_H
#define FIXED_H

// Fixed-point (format 36.28) library.
// This fixed-point implementation is based on the work of Anthony Williams.
// http://www.ddj.com/cpp/207000448

typedef struct fixed {
	int64_t val;
} fixed_t;

#define FIXED_BITS       64
#define FIXED_FRAC_BITS  28
#define FIXED_INT_BITS   36
#define FIXED_RESOLUTION 0x0000000010000000LL
#define FIXED_INT_MASK   0xfffffffff0000000LL
#define FIXED_FRAC_MASK  0x000000000fffffffLL

fixed_t fixed_from_int32(int32_t i);
fixed_t fixed_from_int64(int64_t i);
int32_t fixed_to_int32(fixed_t f);
int64_t fixed_to_int64(fixed_t f);

fixed_t fixed_from_double(double x);
double fixed_to_double(fixed_t f);
fixed_t fixed_from_float(float x);
float fixed_to_float(fixed_t f);

fixed_t fixed_from_string(const char *str);
void fixed_to_string(fixed_t f, char *buf, int len); // len = size of buffer

fixed_t fixed_add(fixed_t a, fixed_t b);
fixed_t fixed_sub(fixed_t a, fixed_t b);
fixed_t fixed_mul(fixed_t a, fixed_t b);
fixed_t fixed_div(fixed_t a, fixed_t b);

fixed_t fixed_floor(fixed_t a);
fixed_t fixed_ceil(fixed_t a);
fixed_t fixed_sqrt(fixed_t a);

fixed_t fixed_exp(fixed_t a);
fixed_t fixed_log(fixed_t a); // natural logarithm

void fixed_sin_cos(fixed_t theta, fixed_t *s, fixed_t *c);
fixed_t fixed_sin(fixed_t a);
fixed_t fixed_cos(fixed_t a);
fixed_t fixed_tan(fixed_t a);
fixed_t fixed_atan(fixed_t a);
void fixed_to_polar(fixed_t x, fixed_t y, fixed_t *r, fixed_t *theta);

fixed_t fixed_neg(fixed_t a);
fixed_t fixed_abs(fixed_t a);

fixed_t fixed_min(fixed_t a, fixed_t b);
fixed_t fixed_max(fixed_t a, fixed_t b);

extern const fixed_t FIXED_INF;
extern const fixed_t FIXED_NINF;
extern const fixed_t FIXED_ONE;
extern const fixed_t FIXED_HALF;
extern const fixed_t FIXED_QUARTER;
extern const fixed_t FIXED_ZERO;
extern const fixed_t FIXED_PI;
extern const fixed_t FIXED_TWO_PI;
extern const fixed_t FIXED_HALF_PI;
extern const fixed_t FIXED_QUARTER_PI;

#endif
